package com.hxgz.steel.service.Impl;

import com.hxgz.steel.common.ServerResponse;
import com.hxgz.steel.dao.*;
import com.hxgz.steel.domain.*;
import com.hxgz.steel.dto.ExtendMerchantDto;
import com.hxgz.steel.dto.ListAsksDto;
import com.hxgz.steel.service.AskBuyService;
import com.hxgz.steel.util.CatalogExcelUtil;
import com.hxgz.steel.util.CommonUtils;
import com.hxgz.steel.util.DateTimeUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.*;

@Service("askBuyService")
public class AskBuyServiceImpl implements AskBuyService {

    @Autowired
    private AskBuyMapper askBuyMapper;
    @Autowired
    private AskInfoMapper askInfoMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private QuotationMapper quotationMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SocerManagerMapper socerManagerMapper;
    @Autowired
    private IntegralMapper integralMapper;
    @Autowired
    private MerchantMapper merchantMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse initiateAskBuy(AskBuy askBuy, List<AskInfo> itemList, User user) {
        Long myMerchantId = null;
        ExtendMerchantDto merchantByuserId = merchantMapper.getMerchantByuserId(user.getId());
        if (merchantByuserId != null) {
            myMerchantId = merchantByuserId.getId();
        }
        User userScore = userMapper.selectByPrimaryKey(user.getId());
        //减少积分 积分规则id
        Long integralId = Long.valueOf(6);
        //查询积分信息
        SocerManager socerManager = socerManagerMapper.selectByPrimaryKey(integralId);
        if (new Integer(1).equals(socerManager.getStatus())) {
            if (userScore.getScore() < Integer.parseInt(socerManager.getSocer())) {
                return ServerResponse.createByErrorMessage("积分不足");
            }
        }
        String aksNum = "QG" + CommonUtils.generateUUID();
        askBuy.setAskNum(aksNum);
        askBuy.setCreateTime(new Date());
        askBuy.setUpdateTime(new Date());
        askBuy.setStatus(0);//正在求购
        int count = askBuyMapper.insertSelective(askBuy);

        if (count > 0) {
            int sucCount = 0;
            for (int i = 0; i < itemList.size(); i++) {
                AskInfo askInfo = new AskInfo();
                askInfo.setAskId(askBuy.getId());
                askInfo.setKind(itemList.get(i).getKind());
                askInfo.setCategoryId(itemList.get(i).getCategoryId());
                askInfo.setCommodity(itemList.get(i).getCommodity());
                askInfo.setProductName(itemList.get(i).getProductName());
                askInfo.setTexture(itemList.get(i).getTexture());
                askInfo.setSpecification(itemList.get(i).getSpecification());
                askInfo.setQuantity(itemList.get(i).getQuantity());
                askInfo.setUnit(itemList.get(i).getUnit());
                askInfo.setArea(itemList.get(i).getArea());
                if (askInfoMapper.insertSelective(askInfo) > 0) {
                    sucCount += 1;
                }
            }
            //匹配商户，如果是平台发起的求购才匹配商户，指定商家发起的求购不匹配商户
            if (StringUtils.isEmpty(askBuy.getMerchantName()) || askBuy.getMerchantId() == null) {
                //平台求购单里面商品数据为1条的时候的匹配
                if (itemList != null && itemList.size() == 1) {
                    for (AskInfo info : itemList) {
                        //获取匹配了商品品名的店铺id，并存入对象Quotation中
                        Set<Long> mIds = quotationMapper.getMerchantIdByTopName(info.getCommodity(), myMerchantId);
                        ArrayList<Long> merchantIds = new ArrayList<>(mIds);
                        //随机打乱匹配的店铺id集合
                        Collections.shuffle(merchantIds);
                        if (merchantIds != null && merchantIds.size() > 10) {
                            List<Long> merchantIds2 = merchantIds.subList(0, 10);
                            for (Long merchantId : merchantIds2) {
                                Quotation quotation = new Quotation();
                                quotation.setAskId(askBuy.getId());
                                quotation.setMerchantId(merchantId);
                                //把上面的封装好的Quotation对象写入Quotation表中
                                quotationMapper.insertSelective(quotation);
                            }
                        }
                        if (merchantIds != null && merchantIds.size() > 0 && merchantIds.size() <= 10) {
                            for (Long merchantId : merchantIds) {
                                Quotation quotation = new Quotation();
                                quotation.setAskId(askBuy.getId());
                                quotation.setMerchantId(merchantId);
                                //把上面的封装好的Quotation对象写入Quotation表中
                                quotationMapper.insertSelective(quotation);
                            }
                        }
                    }
                    //平台求购单里面商品数据为多条的时候的匹配
                } else if (itemList != null && itemList.size() > 1) {
                    HashSet<String> set = new HashSet<>();
                    //多个商品数据可能存在品名一样的，所以用set去重复的品名
                    for (int i = 0; i < itemList.size(); i++) {
                        AskInfo askInfo = itemList.get(i);
                        set.add(askInfo.getCommodity());
                    }
                    //当商品数据多条但品名经过去重后只有一条，那就按照一条商品数据的品名去匹配
                    if (set != null && set.size() == 1) {
                        for (String s : set) {
                            //获取匹配了商品品名的店铺id，并存入对象Quotation中
                            Set<Long> setMIds = quotationMapper.getMerchantIdByTopName(s, myMerchantId);
                            ArrayList<Quotation> merchantIds = new ArrayList<>();
                            for (Long setMId : setMIds) {
                                Quotation quotation = new Quotation();
                                quotation.setMerchantId(setMId);
                                merchantIds.add(quotation);
                            }
//                            List<Quotation> merchantIds = quotationMapper.selectMerchantIdByTopName(s);
                            //随即打乱匹配的店铺id集合
                            Collections.shuffle(merchantIds);
                            //当匹配的店铺多余十条时只截取十条数据存入报价行情信息表中
                            if (merchantIds != null && merchantIds.size() > 10) {
                                List<Quotation> merchantIds2 = merchantIds.subList(0, 10);
                                for (Quotation merchantId : merchantIds2) {
                                    //把平台求购单的id也存入到Quotation中
                                    merchantId.setAskId(askBuy.getId());
                                    //把上面的封装好的Quotation对象写入Quotation表中
                                    quotationMapper.insertSelective(merchantId);
                                }
                            }
                            //当匹配的店铺少余十条时全部存入报价行情信息表中
                            if (merchantIds != null && merchantIds.size() > 0 && merchantIds.size() <= 10) {
                                for (Quotation merchantId : merchantIds) {
                                    //把平台求购单的id也存入到Quotation中
                                    merchantId.setAskId(askBuy.getId());
                                    //把上面的封装好的Quotation对象写入Quotation表中
                                    quotationMapper.insertSelective(merchantId);
                                }
                            }
                        }

                    }
                    //当商品数据多条但品名经过去重后有多条，按照多个品名去匹配
                    if (set != null && set.size() > 1) {
                        HashMap<Integer, List<Quotation>> map = new HashMap<>();
                        ArrayList<String> list = new ArrayList<>(set);
                        for (int i = 0; i < list.size(); i++) {
                            Set<Long> setMIds = quotationMapper.getMerchantIdByTopName(list.get(i), myMerchantId);
                            ArrayList<Quotation> merchantIds = new ArrayList<>();
                            for (Long setMId : setMIds) {
                                Quotation quotation = new Quotation();
                                quotation.setMerchantId(setMId);
                                merchantIds.add(quotation);
                            }
//                            List<Quotation> merchantIds = quotationMapper.selectMerchantIdByTopName(list.get(i));
                            map.put(i, merchantIds);
                        }
                        ArrayList<Long> longs = new ArrayList<>();
                        //获取map的key集合，并循环遍历得到value值，并把得到的value值进行遍历
                        Set<Integer> integers = map.keySet();
                        for (Integer integer : integers) {
                            List<Quotation> quotations = map.get(integer);
                            for (Quotation quotation : quotations) {
                                Long merchantId = quotation.getMerchantId();
                                longs.add(merchantId);
                            }
                        }
                        Collections.sort(longs);
                        // countMap的key是店铺id,value是店铺id出现的次数，店铺id出现的次数多代表匹配的品名个数越多
                        HashMap<Long, Long> countMap = new HashMap<>();
                        ArrayList<Long> longs1 = new ArrayList<>(longs);
                        for (int i = 0; i < longs.size(); i++) {
                            long count1 = 0;//统计店铺id出现的次数
                            for (int j = 0; j < longs1.size(); j++) {
                                if (longs.get(i).equals(longs1.get(j))) {
                                    count1++;
                                }
                            }
                            countMap.put(longs.get(i), count1);
                        }
                        //根据map当中的value值进行倒序排列，value值越大代表着根据品名匹配度越高
                        Set<Map.Entry<Long, Long>> entries = countMap.entrySet();
                        ArrayList<Map.Entry<Long, Long>> entries1 = new ArrayList<>(entries);
                        Collections.sort(entries1, new Comparator<Map.Entry<Long, Long>>() {
                            @Override
                            public int compare(Map.Entry<Long, Long> o1, Map.Entry<Long, Long> o2) {
                                if (o2.getValue() > o1.getValue()) {
                                    return 0;
                                } else if (o2.getValue().equals(o1.getValue())) {
                                    //这一部是因为当匹配度一样高的时候，随机排序
                                    double random = Math.random();
                                    if (random >= 0.5) {
                                        return 0;
                                    } else {
                                        return -1;
                                    }
                                } else {
                                    return -1;
                                }
                            }
                        });
                        //既然已经根据value值进行了倒序排列，取出map中的key：店铺id,存入list中截取前十条数据
                        ArrayList<Long> merchantIdList = new ArrayList<>();
                        for (Map.Entry<Long, Long> longLongEntry : entries1) {
                            merchantIdList.add(longLongEntry.getKey());
                        }
                        if (merchantIdList.size() > 10) {
                            //截取集合中前十条数据
                            List<Long> merchantIds = merchantIdList.subList(0, 10);
                            for (Long merchantId : merchantIds) {
                                Quotation qn = new Quotation();
                                qn.setMerchantId(merchantId);
                                qn.setAskId(askBuy.getId());
                                quotationMapper.insertSelective(qn);
                            }
                        }
                        if (merchantIdList.size() <= 10 && merchantIdList.size() > 0) {
                            for (Long merchantId : merchantIdList) {
                                Quotation qn = new Quotation();
                                qn.setMerchantId(merchantId);
                                qn.setAskId(askBuy.getId());
                                quotationMapper.insertSelective(qn);
                            }
                        }
                    }
                }
            } else {
                Quotation quotation = new Quotation();
                quotation.setMerchantId(askBuy.getMerchantId());
                quotation.setAskId(askBuy.getId());
                quotationMapper.insertSelective(quotation);
            }

            //添加实单求购信息
            if (socerManager.getStatus().equals(1)) {
                //原有积分
                int oldScore = userScore.getScore();
                //需要减少的积分
                int subScore = Integer.valueOf(socerManager.getSocer());
                //添加后的积分
                int newScore = oldScore - subScore;
                userScore.setScore(newScore);
                //更新用户数据
                int userSuccess = userMapper.updateByPrimaryKeySelective(userScore);
                Integral integral = new Integral();
                integral.setUserId(askBuy.getUserId());
                integral.setInSource(integralId);
                integral.setType(1);
                integral.setInChange(subScore);
                //插入积分明细
                int isSuccess = integralMapper.insertSelective(integral);
                if (userSuccess < 0 || isSuccess < 0) {
                    return ServerResponse.createByErrorMessage("积分修改失败");
                }
            }
            if (sucCount == itemList.size()) {
                return ServerResponse.createBySuccessMessage("提交成功");
            }
        }
        return ServerResponse.createByErrorMessage("提交失败");
    }

    @Override
    public void outCataLogExcle(HttpServletResponse response) throws Exception {
        Workbook wb = new HSSFWorkbook();
        Sheet sheet = wb.createSheet("导入模板");

        // 第一行
        Row row = sheet.createRow(0);
        CellStyle style = CatalogExcelUtil.getHeadStyle(wb);

        CatalogExcelUtil.initCell(row.createCell(0), style, "分类");
        CatalogExcelUtil.initCell(row.createCell(1), style, "品名");
        CatalogExcelUtil.initCell(row.createCell(2), style, "商品名称");
        CatalogExcelUtil.initCell(row.createCell(3), style, "材质");
        CatalogExcelUtil.initCell(row.createCell(4), style, "规格");
        CatalogExcelUtil.initCell(row.createCell(5), style, "数量");
        CatalogExcelUtil.initCell(row.createCell(6), style, "单位");
        CatalogExcelUtil.initCell(row.createCell(7), style, "地区");

        // 分类
        String[] kind = new String[]{"风类", "水类", "电类", "消防类"};
        // 第3列的第1行到第21行单元格部门下拉 ，可替换为从数据库的部门表数据，
        // hidden_depart 为隐藏的sheet的别名，1为这个sheet的索引 ，考虑到有多个列绑定下拉列表
        wb = dropDownList2003(wb, sheet, kind, 1, 20, 0, 0, "hidden_kind", 1);

        // 品名
        List<String> commodityList = categoryMapper.getTpyeInfo("品名");
        if (commodityList.size() > 0) {
            String[] commodity = new String[commodityList.size()];
            commodityList.toArray(commodity);
            wb = dropDownList2003(wb, sheet, commodity, 1, 20, 1, 1, "hidden_commodity", 2);
        }

        // 商品名称
        List<String> productNameList = categoryMapper.getTpyeInfo("商品名称");
        if (productNameList.size() > 0) {
            String[] productName = new String[productNameList.size()];
            productNameList.toArray(productName);
            wb = dropDownList2003(wb, sheet, productName, 1, 20, 2, 2, "hidden_productName", 2);
        }
        // 材质
        List<String> textureList = categoryMapper.getTpyeInfo("材质");
        if (textureList.size() > 0) {
            String[] texture = new String[textureList.size()];
            textureList.toArray(texture);
            wb = dropDownList2003(wb, sheet, texture, 1, 20, 3, 3, "hidden_texture", 2);
        }
        //数量  change by liuhuan 20190619 对数量做出只能填写整数的限定 目前限定20行
       /* for(int i=1;i<21;i++){
            Row thisRow = wb.getSheet("导入模板").getRow(i);
            CellStyle  cStyle = wb.createCellStyle();
            thisRow.createCell(0).setCellValue("0.1");
            org.apache.poi.hssf.usermodel.HSSFDataFormat df =(HSSFDataFormat) wb.createDataFormat(); // 此处设置数据格式
            cStyle.setDataFormat(df.getBuiltinFormat("0"));
            thisRow.createCell(5).setCellStyle(cStyle);
        }*/
        // 规格
        List<String> specificationList = categoryMapper.getTpyeInfo("规格");
        if (specificationList.size() > 0) {
            String[] specification = new String[specificationList.size()];
            specificationList.toArray(specification);
            wb = dropDownList2003(wb, sheet, specification, 1, 20, 4, 4, "hidden_specification", 2);
        }
        // 单位
        String[] unit = new String[]{"台", "件", "袋", "包", "条", "吨", "根", "头", "个", "只", "对", "片", "盒"};
        wb = dropDownList2003(wb, sheet, unit, 1, 20, 6, 6, "hidden_unit", 2);

        // 地区
        String[] area = new String[]{"华中", "华南", "华北", "华东"};
        wb = dropDownList2003(wb, sheet, area, 1, 20, 7, 7, "hidden_area", 2);


        OutputStream output = response.getOutputStream();
        response.reset();
        String fileName = "求购文件模板.xls";
        String changeFileName = new String(fileName.getBytes("GB2312"), "ISO_8859_1");
        response.setHeader("Content-disposition", "attachment; filename=" + changeFileName + "");
        response.setContentType("application/msexcel");
        wb.write(output);
        output.close();
    }

    /**
     * @param wb               HSSFWorkbook对象
     * @param realSheet        需要操作的sheet对象
     * @param datas            下拉的列表数据
     * @param startRow         开始行
     * @param endRow           结束行
     * @param startCol         开始列
     * @param endCol           结束列
     * @param hiddenSheetName  隐藏的sheet名
     * @param hiddenSheetIndex 隐藏的sheet索引
     * @return
     * @throws Exception
     */
    public static HSSFWorkbook dropDownList2003(Workbook wb, Sheet realSheet, String[] datas, int startRow, int endRow,
                                                int startCol, int endCol, String hiddenSheetName, int hiddenSheetIndex)
            throws Exception {

        HSSFWorkbook workbook = (HSSFWorkbook) wb;
        // 创建一个数据源sheet
        HSSFSheet hidden = workbook.createSheet(hiddenSheetName);
        // 数据源sheet页不显示
        workbook.setSheetHidden(hiddenSheetIndex, true);
        // 将下拉列表的数据放在数据源sheet上
        HSSFRow row = null;
        HSSFCell cell = null;
        for (int i = 0, length = datas.length; i < length; i++) {
            row = hidden.createRow(i);
            cell = row.createCell(0);
            cell.setCellValue(datas[i]);
        }
        //2016-12-15更新，遇到问题：生成的excel下拉框还是可以手动编辑，不满足
        //HSSFName namedCell = workbook.createName();
        //namedCell.setNameName(hiddenSheetName);
        // A1 到 Adatas.length 表示第一列的第一行到datas.length行，需要与前一步生成的隐藏的数据源sheet数据位置对应
        //namedCell.setRefersToFormula(hiddenSheetName + "!$A$1:$A" + datas.length);
        // 指定下拉数据时，给定目标数据范围 hiddenSheetName!$A$1:$A5   隐藏sheet的A1到A5格的数据
        DVConstraint constraint = DVConstraint.createFormulaListConstraint(hiddenSheetName + "!$A$1:$A" + datas.length);
        CellRangeAddressList addressList = null;
        HSSFDataValidation validation = null;
        row = null;
        cell = null;
        // 单元格样式
        CellStyle style = workbook.createCellStyle();
        style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0"));
//        style.setAlignment(CellStyle.ALIGN_CENTER);
//        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        // 循环指定单元格下拉数据
        for (int i = startRow; i <= endRow; i++) {
            row = (HSSFRow) realSheet.createRow(i);
            cell = row.createCell(startCol);
            cell.setCellStyle(style);
            addressList = new CellRangeAddressList(i, i, startCol, endCol);
            validation = new HSSFDataValidation(addressList, constraint);
            realSheet.addValidationData(validation);
        }

        return workbook;
    }

    @Override
    public ServerResponse uploadExcel(String path) throws Exception {
        List<AskInfo> askInfoList = new ArrayList<AskInfo>();
        FileInputStream fileIn = new FileInputStream(path);
        //根据指定的文件输入流导入Excel从而产生Workbook对象
        Workbook wb0 = new HSSFWorkbook(fileIn);
        /*XSSFWorkbook wb1 */
        //获取Excel文档中的第一个表单
        Sheet sht0 = wb0.getSheetAt(0);
        //对Sheet中的每一行进行迭代
        for (Row r : sht0) {
            //如果当前行的行号（从0开始）未达到2（第三行）则从新循环
            if (r.getRowNum() < 1) {
                continue;
            }
            if (r == null || r.equals("")) {
                continue;
            }
            if (r.getCell(0) == null) {
                break;
            }
            r.getCell(0).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(1).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(2).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(3).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(4).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(5).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(6).setCellType(Cell.CELL_TYPE_STRING);
            r.getCell(7).setCellType(Cell.CELL_TYPE_STRING);

            AskInfo askInfo = new AskInfo();
            askInfo.setKind(r.getCell(0).getStringCellValue());
            askInfo.setCommodity(r.getCell(1).getStringCellValue());
            askInfo.setProductName(r.getCell(2).getStringCellValue());
            askInfo.setTexture(r.getCell(3).getStringCellValue());
            askInfo.setSpecification(r.getCell(4).getStringCellValue());
//            String quantityAndUnit=r.getCell(5).getStringCellValue();
//            String numStr = ExtractStringUtils.numStr(quantityAndUnit);
//            if (numStr==null||"".equals(numStr)){
//                askInfo.setQuantity("0");
//            }else {
//                askInfo.setQuantity(numStr);
//            }
//            askInfo.setUnit(ExtractStringUtils.gbkStr(quantityAndUnit));
            if (!(r.getCell(5).getStringCellValue().matches("^[1-9]\\d*$"))) {
                throw new RuntimeException("数量请填正整数!");
            }
            askInfo.setQuantity(r.getCell(5).getStringCellValue());
            askInfo.setUnit(r.getCell(6).getStringCellValue());
            askInfo.setArea(r.getCell(7).getStringCellValue());
//            askInfo.setPrice(new BigDecimal(r.getCell(7).getStringCellValue()));
            askInfoList.add(askInfo);
        }

        fileIn.close();

        return ServerResponse.createBySuccess(askInfoList);
    }

    @Override
    public void listAsks() {
        //查询所有在求购中的求购单
        List<ListAsksDto> listAsksVos = askBuyMapper.getListAsksVos();
        Long endTime = 0L;
        //获取报价时限并同当前时间比对
        List<Long> ids = new ArrayList<>();
        for (ListAsksDto askBuy : listAsksVos) {
            endTime = DateTimeUtil.addHours(new Date(), askBuy.getTimeLimit() * 12).getTime();
            if (endTime <= new Date().getTime()) {
                ids.add(askBuy.getId());
            }
        }
        if (CollectionUtils.isNotEmpty(ids)) {
            askBuyMapper.updateStatusInIds(ids);
        }
    }
}
